package io.fft.flight.common.aspect;

import io.fft.flight.common.annotation.EntityFieldDefault;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Collection;

/**
 * 插入数据切面
 */
@Aspect
@Component
public class InsertAspect {
    @Pointcut("execution(public * io.fft.flight.common.service.BaseService.insert(..)) || execution(public * io.fft.flight.common.service.BaseService.insertBatch(..))")
    public void pointCut() {
    }

    @Before("pointCut()")
    public void before(JoinPoint joinPoint) throws NoSuchMethodException {
        Object arg = joinPoint.getArgs()[0];
        if (arg instanceof Collection) {
            Collection<?> c = (Collection<?>) arg;
            for (Object o : c) {
                setDefaultValue(o);
            }
        } else {
            setDefaultValue(arg);
        }
    }

    private void setDefaultValue(Object arg) {
        for (Field field : arg.getClass().getDeclaredFields()) {
            EntityFieldDefault annotation = field.getAnnotation(EntityFieldDefault.class);
            if (null != annotation) {
                Class<?> type = field.getType();
                try {
                    PropertyDescriptor propertyDescriptor = new PropertyDescriptor(field.getName(), arg.getClass());
                    Method writeMethod = propertyDescriptor.getWriteMethod();
                    field.setAccessible(true);
                    Object value = field.get(arg);
                    if (null != value) {
                        // 本身有值，不处理
                        continue;
                    }
                    if (type.equals(Long.class)) {
                        writeMethod.invoke(arg, Long.valueOf(annotation.value()));
                    } else if (type.equals(Integer.class)) {
                        writeMethod.invoke(arg, Integer.valueOf(annotation.value()));
                    } else if (type.equals(String.class)) {
                        writeMethod.invoke(arg, annotation.value());
                    } else {
                        throw new RuntimeException("不支持的类型" + type.getTypeName());
                    }
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }

}
